ARG PYTHON_VERSION=3.11
ARG OS_VERSION=slim
ARG RUNTIME_EDITION=postgres

## build stage

FROM python:${PYTHON_VERSION}-${OS_VERSION} AS build

ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT

# Set the working directory
WORKDIR /api

# Copy constraints files
COPY --from=api constraints.txt ./constraints.txt
# Assert that both the license and storage constraints are non-empty
RUN --mount=type=bind,from=license,source=constraints.txt,target=/tmp/constraints.txt \
    cat /tmp/constraints.txt >> /api/constraints.txt
RUN --mount=type=bind,from=storage,source=constraints.txt,target=/tmp/constraints.txt \
    cat /tmp/constraints.txt >> /api/constraints.txt

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Install all dependencies
RUN PIP_ROOT_USER_ACTION=ignore PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -r constraints.txt \
    && python -c "import compileall; compileall.compile_path(maxlevels=1000, legacy=True)"

# Copy the rest of application code
RUN cp /api/constraints.txt /tmp/saved_constraints.txt
COPY --from=api . /api
RUN cp /tmp/saved_constraints.txt /api/constraints.txt
# Overwrite the storage module
COPY --from=storage . /storage
COPY --from=license langgraph_license /api/langgraph_license
RUN rm -rf /api/tests /api/langgraph_api/js/tests

# Install editable wheels, byte-compile **everything** we own, then strip sources
RUN PIP_ROOT_USER_ACTION=ignore PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir --no-deps -e /api /storage \
    && python -c \
        "import compileall, site, glob, os; \
         compileall.compile_path('/storage', maxlevels=1000, legacy=True); \
         compileall.compile_path('/api',      maxlevels=1000, legacy=True); \
         sp = site.getsitepackages()[0]; \
         [compileall.compile_path(p, maxlevels=1000, legacy=True) \
          for p in glob.glob(os.path.join(sp, 'langgraph_*'))]" \
    && find /storage \
           /api/langgraph_api \
           /api/langgraph_license \
           /api/langgraph_runtime \
           /api/scripts \
           /usr/local/lib/python*/site-packages/langgraph_* \
         -type f -name '*.py' ! -name '__init__.py' -print0 | xargs -0 rm

## final stage

FROM python:${PYTHON_VERSION}-${OS_VERSION} AS final

ARG PYTHON_VERSION
ARG REVISION
ARG VARIANT
ARG OS_VERSION
ARG RUNTIME_EDITION

# Install runtime dependencies such as git
RUN if [ "${OS_VERSION}" != "slim-bullseye" ]; then \
    apt-get update \
    && apt-get install -y --no-install-recommends git \
    && rm -rf /var/lib/apt/lists/*; \
    fi

# Copy from build stage
COPY --from=build /api /api
COPY --from=build /storage /storage
COPY --from=build /usr/local/lib/python${PYTHON_VERSION}/site-packages /usr/local/lib/python${PYTHON_VERSION}/site-packages
COPY --from=build /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=build /usr/local/bin/langgraph-verify-graphs /usr/local/bin/langgraph-verify-graphs
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Set working directory
WORKDIR /api

# Enable Python stack traces on segfaults https://stackoverflow.com/a/29246977
# Ensure Python does not buffer output, which is recommended when inside a container.
ENV PYTHONFAULTHANDLER=1 PYTHONUNBUFFERED=True PORT=8000 PIP_ROOT_USER_ACTION=ignore N_WORKERS=1 N_JOBS_PER_WORKER=10 LANGSMITH_LANGGRAPH_API_REVISION=$REVISION LANGSMITH_LANGGRAPH_API_VARIANT=$VARIANT LANGGRAPH_RUNTIME_EDITION=$RUNTIME_EDITION

LABEL org.opencontainers.image.revision=$REVISION

HEALTHCHECK --interval=5s --timeout=2s --retries=5 CMD [ "python", "/api/healthcheck.py" ]

# https://docs.datadoghq.com/serverless/google_cloud_run/#how-serverless-init-works
COPY --from=datadog/serverless-init:1 /datadog-init /app/datadog-init
# Install ddtrace only for Python 3.11 or 3.12
RUN if [ "${PYTHON_VERSION}" = "3.11" ] || [ "${PYTHON_VERSION}" = "3.12" ]; then \
        uv pip install --system --target /dd_tracer/python/ ddtrace; \
    fi

RUN chmod +x /storage/entrypoint.sh && chmod +x /storage/install-node.sh
ENTRYPOINT ["/storage/entrypoint.sh"]
